{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "8dbfe029-b63f-4520-8fab-0154ad80022b",
   "metadata": {},
   "source": [
    "## Agent\n",
    "官方LangChain文档完美地描述了Agent的概念\n",
    "\n",
    " >  一些应用程序不仅需要对LLM/ 其他工具预定调用链,还可能需要依赖于用户输入的未知链。在这些类型的链中，有一个可以访问一套工具的“Agent”。\n",
    " >  根据用户输入, Agent 可以** 决定这些工具中的哪一个（如果有的话）。\n",
    "\n",
    "基本上Agent不仅将LLM用于文本输出，还用于决策。这就是Agent的酷炫和强大之处。\n",
    "Sam Altman 强调LLM是优秀的“推理引擎”。Agent的出现正是利用了这一点。\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "22db1233-7fcc-444d-a6ad-96ddc6ee2f72",
   "metadata": {},
   "source": [
    "##  Agent\n",
    "驱动决策的语言模型\n",
    "\n",
    "更具体地说：Agent接收输入并返回于要采取的操作以及操作输入相对应的响应。可以访问下面的链接（https://python.langchain.com/v0.1/docs/modules/agents/agent_types）看到不同类型的Agent(适合不同的用例)。\n",
    "\n",
    "目前langchain的agent框架基本上已经完全向langgraph进行迁移。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "967cba78-cd9b-4512-95a4-3c07d7d51cf1",
   "metadata": {},
   "source": [
    "## 工具包\n",
    "一个特定的Agent可以从中选择工具组"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "5e8460ed-3fd9-4836-be88-f5f210b42b29",
   "metadata": {},
   "outputs": [],
   "source": [
    "!pip install -q google-search-results"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "ad0773cc-3cfd-417b-8b20-04fe15e048a5",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain.agents import load_tools\n",
    "from langchain.agents import initialize_agent\n",
    "import json\n",
    "from langchain_openai import ChatOpenAI\n",
    "\n",
    "import os\n",
    "from openai import OpenAI\n",
    "from dotenv import load_dotenv,find_dotenv\n",
    "\n",
    "load_dotenv(find_dotenv())  # 加载 .env 文件中的环境变量\n",
    "\n",
    "llm = ChatOpenAI(model_name=\"gpt-4o\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "c379da07-2f49-4e9b-b8b4-aec618d00e5d",
   "metadata": {},
   "outputs": [],
   "source": [
    "# serpapi_api_key 官网 https://serpapi.com/\n",
    "serpapi_api_key = os.getenv(\"SERP_API_KEY\",\"\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "a1b860f8-ba7b-4315-99d7-85e76fe5ea51",
   "metadata": {},
   "outputs": [],
   "source": [
    "toolkit = load_tools(['serpapi'],llm=llm,serpapi_api_key=serpapi_api_key)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "8ef25112-1865-4a9b-be34-f8f1afda1dea",
   "metadata": {},
   "outputs": [],
   "source": [
    "# agent = initialize_agent(toolkit,llm,agent ='zero-shot-react-description',verbose=True,return_intermediate_steps=True)\n",
    "\n",
    "agent = initialize_agent(\n",
    "    tools=toolkit,\n",
    "    llm=llm,\n",
    "    agent='zero-shot-react-description',\n",
    "    verbose=True,\n",
    "    return_intermediate_steps=True,\n",
    "    handle_parsing_errors=True  # ✅ 添加错误处理\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "add2526c-7a9c-48e4-97f3-5194feff8dfa",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Error in StdOutCallbackHandler.on_chain_start callback: AttributeError(\"'NoneType' object has no attribute 'get'\")\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\u001b[32;1m\u001b[1;3m这是一个关于当前事件的问题，我需要使用搜索引擎来获取今天上证指数的收盘点数。\n",
      "Action: Search\n",
      "Action Input: \"今天上证指数收盘点数\"\u001b[0m\n",
      "Observation: \u001b[36;1m\u001b[1;3m上证指数3280.34 4.34(+0.13%)_财经频道_腾讯网\u001b[0m\n",
      "Thought:\u001b[32;1m\u001b[1;3m我现在知道了今天上证指数的收盘点数。\n",
      "Final Answer: 今天上证指数收盘为3280.34点。\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    }
   ],
   "source": [
    "response = agent.invoke({\"input\":\"今天上证指数收盘多少点？\"})\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "0c1057b8-2830-4d07-83db-96a7a04e4ecc",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Error in StdOutCallbackHandler.on_chain_start callback: AttributeError(\"'NoneType' object has no attribute 'get'\")\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\u001b[32;1m\u001b[1;3m需要获取上证指数的最新收盘数据。\n",
      "Action: Search\n",
      "Action Input: 今天上证指数收盘点数\n",
      "\u001b[0m\n",
      "Observation: \u001b[36;1m\u001b[1;3m上证指数3280.34 4.34(+0.13%)_财经频道_腾讯网\u001b[0m\n",
      "Thought:\u001b[32;1m\u001b[1;3m上证指数今日收盘为3280.34点，涨幅为4.34点，约0.13%。\u001b[0m\n",
      "Observation: Invalid Format: Missing 'Action:' after 'Thought:\n",
      "Thought:\u001b[32;1m\u001b[1;3mAction: Search\n",
      "Action Input: 今天上证指数收盘点数\n",
      "\n",
      "\u001b[0m\n",
      "Observation: \u001b[36;1m\u001b[1;3m上证指数3280.34 4.34(+0.13%)_财经频道_腾讯网\u001b[0m\n",
      "Thought:\u001b[32;1m\u001b[1;3m上证指数今日收盘为3280.34点，涨幅为4.34点，约0.13%。\u001b[0m\n",
      "Observation: Invalid Format: Missing 'Action:' after 'Thought:\n",
      "Thought:\u001b[32;1m\u001b[1;3mI now know the final answer.\n",
      "Final Answer: 今天上证指数收盘为3280.34点，涨幅为4.34点，约0.13%。\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n",
      "今天上证指数收盘为3280.34点，涨幅为4.34点，约0.13%。\n"
     ]
    }
   ],
   "source": [
    "from langchain.agents import load_tools, initialize_agent\n",
    "from langchain_openai import ChatOpenAI\n",
    "import os\n",
    "from dotenv import load_dotenv, find_dotenv\n",
    "\n",
    "# 加载环境变量\n",
    "load_dotenv(find_dotenv())\n",
    "\n",
    "# 初始化模型\n",
    "llm = ChatOpenAI(model_name=\"gpt-4o\")\n",
    "\n",
    "# 配置 SerpAPI\n",
    "serpapi_api_key = os.getenv(\"SERP_API_KEY\", \"\")\n",
    "toolkit = load_tools(['serpapi'], llm=llm, serpapi_api_key=serpapi_api_key)\n",
    "\n",
    "# 初始化代理（✅ 添加 handle_parsing_errors）\n",
    "agent = initialize_agent(\n",
    "    tools=toolkit,\n",
    "    llm=llm,\n",
    "    agent='zero-shot-react-description',\n",
    "    verbose=True,\n",
    "    return_intermediate_steps=True,\n",
    "    handle_parsing_errors=True\n",
    ")\n",
    "\n",
    "# 调用代理（✅ 使用 invoke）\n",
    "response = agent.invoke({\"input\": \"今天上证指数收盘多少点？\"})\n",
    "\n",
    "# 打印结果\n",
    "print(response[\"output\"])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "f1a4e4a0-d5b4-456d-bb47-036596a2e95e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Answer the following questions as best you can. You have access to the following tools:\n",
      "\n",
      "Search(query: str, **kwargs: Any) -> str - A search engine. Useful for when you need to answer questions about current events. Input should be a search query.\n",
      "\n",
      "Use the following format:\n",
      "\n",
      "Question: the input question you must answer\n",
      "Thought: you should always think about what to do\n",
      "Action: the action to take, should be one of [Search]\n",
      "Action Input: the input to the action\n",
      "Observation: the result of the action\n",
      "... (this Thought/Action/Action Input/Observation can repeat N times)\n",
      "Thought: I now know the final answer\n",
      "Final Answer: the final answer to the original input question\n",
      "\n",
      "Begin!\n",
      "\n",
      "Question: {input}\n",
      "Thought:{agent_scratchpad}\n"
     ]
    }
   ],
   "source": [
    "print(agent.agent.llm_chain.prompt.template)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "eddea37d-f294-45c0-8bc1-b490073e1010",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3.8",
   "language": "python",
   "name": "py38"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.20"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
